package com.uxsino.simo.incremental.parser;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.uxsino.commons.utils.ArithUtils;
import com.uxsino.reactorq.model.IndicatorValue;
import com.uxsino.simo.incremental.IncrementalParser;
import com.uxsino.simo.incremental.IncrementalUtil;

public class ProcessParser implements IncrementalParser {
    private static final Logger logger = LoggerFactory.getLogger(ProcessParser.class);

    // 时间间隔 (1分钟)
    private final static int MIN_INTERVAL = 60;

    private final static int SIZE = 1024;

    private final static int PERCENT = 100;

    @Override
    public void apply(IndicatorValue oldValue, IndicatorValue value) {
        if (value == null) {
            return;
        }
        Double memTotal = IncrementalUtil.getMemTotalCache(value.entityId);
        JSONArray jsonArray = (JSONArray) JSONArray.toJSON(value.value);

        JSONArray historyArray = new JSONArray();
        Long beginTime = null;
        Long endTime = null;
        Double runTime = null;
        if (oldValue != null) {
            historyArray = (JSONArray) JSONArray.toJSON(oldValue.value);
            beginTime = oldValue.queryTimeMillis;
            endTime = value.queryTimeMillis;
            runTime = ArithUtils.div((endTime - beginTime), 1000);
        }

        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);
            if (oldValue != null) {
                for (int r = 0; r < historyArray.size(); r++) {
                    JSONObject historyValue = historyArray.getJSONObject(r);
                    if (historyValue.getString("run_name") != null && json.getString("run_name") != null && json
                            .getString("run_name").equals(historyValue.getString("run_name")) && json
                            .getString("run_index").equals(historyValue.getString("run_index"))
                            && json.getDouble("run_perf_cpu_usage") == null) {
                        Double processCpuUsage = cpuUsage(json.getString("run_name"), beginTime, endTime,
                                historyValue.getDouble("run_perf_cpu"), json.getDouble("run_perf_cpu"));
                        if (processCpuUsage == 0 && runTime < MIN_INTERVAL) {
                            jsonArray.getJSONObject(i)
                                    .put("run_perf_cpu_usage", historyValue.getString("run_perf_cpu_usage"));
                        } else {
                            jsonArray.getJSONObject(i).put("run_perf_cpu_usage", processCpuUsage);
                        }
                        break;
                    }
                }
            }

            if (memTotal != null && memTotal > 0 && jsonArray.getJSONObject(i).getDouble("run_perf_mem_usage") == null
                    && null != json.getDouble("run_perf_mem")) {
                Double processMenUsage = memUsage(json.getDouble("run_perf_mem"), memTotal);
                jsonArray.getJSONObject(i).put("run_perf_mem_usage", processMenUsage);
            }
        }
        value.value = jsonArray;
    }

    /**
     * 
     * @param startTime 检测时间 单位[毫秒]
     * @param endTime
     * @param beginCpuSlice 表示的是从运行开始到目前时间截止,使用的CPU时间。单位是 [百分之一秒]
     * @param endCpuSlice
     * @return
     */
    private Double cpuUsage(String name, Long startTime, Long endTime, Double beginCpuSlice, Double endCpuSlice) {
        // return ArithUtils.div((endCpuSlice - beginCpuSlice) * millisecond, endTime - startTime);
        Double cpuTime = new Double(0);
        if (endCpuSlice != null && beginCpuSlice != null) {
            cpuTime = ArithUtils.mul((endCpuSlice - beginCpuSlice), 10); // 百分之一秒转为毫秒
        }
        Double runTime = ArithUtils.sub(endTime, startTime);
        if (cpuTime >= 0 && runTime >= 0 && cpuTime < runTime) {
            return ArithUtils.mul(ArithUtils.div(cpuTime, runTime), PERCENT);
        } else {
            logger.error("{}--->cpu:{}-{} = {} # 检测时间:{} - {} = {}", name, endCpuSlice, beginCpuSlice, cpuTime, endTime,
                startTime, runTime);
            return 0D;
        }

    }

    private Double memUsage(Double used, Double total) {
        return ArithUtils.div(used * PERCENT * SIZE, total);
    }
}
